/*
 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     bstefanescu
 */
package org.nuxeo.gwt.habyt.templates.client;

import java.util.ArrayList;
import java.util.List;

import org.nuxeo.gwt.habyt.templates.client.TemplatePanel.Binding;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * The asynchronous task of loading a remote template.
 * 
 * The task is monitoring the loading state of all sub templates and notify the
 * user callback when either all templates were loaded or an error occurred
 * loading one of the template.
 * 
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 * 
 */
class LoadingTask implements AsyncCallback<TemplatePanel>, Constants {

    protected AsyncCallback<TemplatePanel> cb;

    protected TemplatePanel panel;

    protected List<Binding> stack;

    /**
     * Subtask counter. initialized with 1 since the current task is also
     * counted
     */
    protected int cnt = 1;

    LoadingTask(TemplatePanel panel, AsyncCallback<TemplatePanel> cb) {
        this(panel, cb, new ArrayList<TemplatePanel.Binding>());
    }

    LoadingTask(TemplatePanel panel, AsyncCallback<TemplatePanel> cb,
            List<Binding> bindings) {
        this.cb = cb;
        this.panel = panel;
        this.stack = bindings;
    }

    public void pushBinding(Binding binding) {
        stack.add(binding);
    }

    public void popBinding() {
        int size = stack.size();
        if (size > 0) {
            stack.remove(size - 1);
        }
    }

    public Binding getCurrentBinding() {
        int size = stack.size();
        return size == 0 ? null : stack.get(size - 1);
    }

    public LoadingTask subtask() {
        cnt++;
        return new LoadingTask(panel, this, stack);
    }

    public void onFailure(Throwable caught) {
        cnt--;
        if (cb != null) {
            cb.onFailure(caught);
        } else {
            UncaughtExceptionHandler uch = GWT.getUncaughtExceptionHandler();
            if (uch != null) {
                uch.onUncaughtException(caught);
            } else {
                Window.alert(caught.toString());
            }
        }
    }

    public void onSuccess(TemplatePanel result) {
        cnt--;
        if (cnt == 0) { // no more jobs
            if (cb != null) {
                cb.onSuccess(panel);
            }
        }
    }

}
